package com.nifostasky.main.reflex.menthodfield;

/**
 * 通过反射获取方法
 */
/**
 * Class 获取 Method对象的方法
 * | 返回值     | 方法说明                                                     |
 * | :--------- | :----------------------------------------------------------- |
 * | `Method`   | `getMethod(String name, Class<?>... parameterTypes)` 返回一个 `Method` 对象，它反映此 `Class` 对象所表示的类的public方法。（可以获取父类的方法） |
 * | `Method[]` | `getMethods()` 返回所有 `Method` 对象，它反映此 `Class` 对象所表示的类的public方法。（可以获取父类的方法） |
 * | `Method`   | `getDeclaredMethod(String name, Class<?>... parameterTypes)` 返回一个 `Method` 对象，该对象反映此 `Class` 对象所表示的类的public/private方法。（只获取当前类的方法） |
 * | `Method[]` | `getDeclaredMethods()` 返回所有 `Method` 对象，它反映此 `Class` 对象所表示的类的public/private方法。（只获取当前类的方法） |
 */

import lombok.SneakyThrows;

import java.lang.reflect.Method;

/**
 * Method类中方法
 * | `<T extends Annotation>T` | `getAnnotation(Class<T> annotationClass)` 如果存在该元素的指定类型的注解，则返回这些注释，否则返回 null。 |
 * | :------------------------ | :----------------------------------------------------------- |
 * | `Annotation[]`            | `getDeclaredAnnotations()` 返回直接存在于此元素上的所有注解。 |
 * | `Class<?>`                | `getDeclaringClass()` 返回表示声明由此 `Method` 对象表示的方法的类或接口的 `Class` 对象。 |
 * | `Type[]`                  | `getGenericParameterTypes()` 按照声明顺序返回 `Type` 对象的数组，这些对象描述了此 `Method` 对象所表示的方法的形参类型的。 |
 * | `Type`                    | `getGenericReturnType()` 返回表示由此 `Method` 对象所表示方法的正式返回类型的 `Type` 对象。 |
 * | `int`                     | `getModifiers()` 以整数形式返回此 `Method` 对象所表示方法的 Java 语言修饰符。 |
 * | `String`                  | `getName()` 以 `String` 形式返回此 `Method` 对象表示的方法名称。 |
 * | `Annotation[][]`          | `getParameterAnnotations()` 返回表示按照声明顺序对此 `Method` 对象所表示方法的形参进行注解的那个数组的数组。 |
 * | `Class<?>[]`              | `getParameterTypes()` 按照声明顺序返回 `Class` 对象的数组，这些对象描述了此 `Method` 对象所表示的方法的形参类型。 |
 * | `Class<?>`                | `getReturnType()` 返回一个 `Class` 对象，该对象描述了此 `Method` 对象所表示的方法的正式返回类型。 |
 * | `Object`                  | `invoke(Object obj, Object... args)` 对带有指定参数的指定对象调用由此 `Method` 对象表示的底层方法。 |
 * | `boolean`                 | `isVarArgs()` 如果将此方法声明为带有可变数量的参数，则返回 `true`；否则，返回 `false`。 |
 * | `String`                  | `toGenericString()` 返回描述此 `Method` 的字符串，包括类型参数。 |
 * | `void`                    | `setAccessible(boolean flag)` 将此对象的 accessible 标志设置为指示的布尔值,即设置其可访问性。 |
 */
public class MethodClass {

    /**
     * 通过反射调用对象方法示例
     */
    @SneakyThrows
    public static void methodTest(){
        //获取实例
        String classpath = "com.nifostasky.main.reflex.template.Student";
        Class<?> aClass = Class.forName(classpath);
        Object object = aClass.newInstance();
        //获取方法,为学生设置性别为女
        Method setSex = aClass.getMethod("setSex", Boolean.class);
        Method getSex = aClass.getMethod("getSex");
        setSex.invoke(object, true);
        Boolean invoke = (Boolean) getSex.invoke(object);
        System.out.println("----------------------" + invoke.toString());
        // 如果方法为private，则可以设置访问权限为true，即可invoke : setSex.setAccessible(true);
        // 可以调用到父类方法 getMethod
        // 获取不到父类方法 getDeclaredMethod
    }

    public static void main(String[] args) {
        MethodClass.methodTest();
    }
}
